/* 
 *  Copyright (C) 2008 Jens Meiß
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package com.googlecode.hmvc4gwt.example.hmvcblog.service.services.blog;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.annotation.Transactional;

import com.googlecode.hmvc4gwt.example.hmvcblog.server.domain.blog.Blog;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.domain.blog.BlogEntry;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.domain.blog.BlogEntryComment;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.domain.user.User;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.blog.IBlogRepository;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.blog.entry.IBlogEntryRepository;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.blog.exceptions.BlogNotFoundException;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.user.IUserRepository;
import com.googlecode.hmvc4gwt.example.hmvcblog.server.repository.user.exceptions.UserSessionNotFoundException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogEditDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogEditIdDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogNewDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogPreviewDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogRemoveDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.BlogUpdateDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.BlogEntryDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.entry.comment.BlogEntryCommentDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogTitleEmptyException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.NotBlogOwnerException;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.dashboard.UserBlogTitleDTO;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.UserSessionId;
import com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.user.exception.NotLoggedInException;

/**
 * This Service provides Blogs :)
 * 
 * @author jens.meiss
 */
@Transactional
public class BlogService implements IBlogService {

	private IBlogEntryRepository blogEntryRepository;

	private IBlogRepository blogRepository;

	private IUserRepository userRepository;

	private static final Log logger = LogFactory.getLog(BlogService.class);

	public void addBlog(BlogNewDTO blogNewDTO) throws BlogTitleEmptyException,
			NotLoggedInException {

		if ((blogNewDTO.getTitle() == null)
				|| (blogNewDTO.getTitle().equals(""))) {
			throw new BlogTitleEmptyException();
		}

		try {
			User user = getUserRepository().findBySessionId(
					blogNewDTO.getSessionId());

			Blog blog = new Blog();
			blog.setUser(user);
			blog.setTitle(blogNewDTO.getTitle());
			blog.setDescription(blogNewDTO.getDescription());
			blog.setDateLastUpdate(new Date());

			getBlogRepository().addBlog(blog);

		} catch (UserSessionNotFoundException e) {
			logger.error(e);
			throw new NotLoggedInException();
		}

	}

	private BlogDTO convertBlog(Blog blog) {

		BlogDTO blogDTO = new BlogDTO();
		blogDTO.setId(blog.getId());
		blogDTO.setTitle(blog.getTitle());
		blogDTO.setDescription(blog.getDescription());
		blogDTO.setNameAuthor(blog.getUser().getLogin());

		return blogDTO;

	}

	public void updateBlog(BlogUpdateDTO blogUpdateDTO)
			throws BlogTitleEmptyException,
			NotLoggedInException,
			com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException,
			NotBlogOwnerException {

		if ((blogUpdateDTO.getTitle() == null)
				|| (blogUpdateDTO.getTitle().equals(""))) {
			throw new BlogTitleEmptyException();
		}

		try {

			User user = getUserRepository().findBySessionId(
					blogUpdateDTO.getSessionId());
			Blog blog = getBlogRepository().findById(blogUpdateDTO.getId());

			if (user.getId() != blog.getUser().getId()) {
				throw new NotBlogOwnerException();
			}

			blog.setDateLastUpdate(new Date());
			blog.setDescription(blogUpdateDTO.getDescription());
			blog.setTitle(blogUpdateDTO.getTitle());
			
			getBlogRepository().update(blog);
			
		} catch (UserSessionNotFoundException e) {
			throw new NotLoggedInException();
		} catch (BlogNotFoundException e) {
			throw new com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException();
		}
	}

	public BlogDTO getBlog(Integer id)
			throws com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException {

		try {
			Blog blog = getBlogRepository().findById(id);

			return convertBlog(blog);

		} catch (BlogNotFoundException e) {
			throw new com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException();
		}

	}

	public BlogDTO getBlog(String name)
			throws com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException {

		try {
			Blog blog = getBlogRepository().findByName(name);

			return convertBlog(blog);

		} catch (BlogNotFoundException e) {
			throw new com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException();
		}
	}

	public IBlogEntryRepository getBlogEntryRepository() {
		return blogEntryRepository;
	}

	public IBlogRepository getBlogRepository() {
		return blogRepository;
	}

	public List<UserBlogTitleDTO> getListBlogTitle(
			UserSessionId userSessionId) throws NotLoggedInException {

		try {
			User user = getUserRepository().findBySessionId(userSessionId.getSessionId());
			List<Blog> listBlog = getBlogRepository().getBlogsOfuser(user);

			List<UserBlogTitleDTO> listBlogTitleDTO = new LinkedList<UserBlogTitleDTO>();
			for (Blog blog : listBlog) {
				UserBlogTitleDTO blogTitleDTO = new UserBlogTitleDTO();
				blogTitleDTO.setId(blog.getId());
				blogTitleDTO.setTitle(blog.getTitle());

				listBlogTitleDTO.add(blogTitleDTO);
			}

			return listBlogTitleDTO;

		} catch (UserSessionNotFoundException e) {
			throw new NotLoggedInException();
		}

		
	}

	public Set<BlogPreviewDTO> getSetBlogPreview() {

		Set<BlogPreviewDTO> setBlogpreviewDTO = new HashSet<BlogPreviewDTO>();
		for (Blog blog : getBlogRepository().getListBlogs()) {

			BlogPreviewDTO blogPreviewDTO = new BlogPreviewDTO();
			blogPreviewDTO.setId(blog.getId());
			blogPreviewDTO.setTitle(blog.getTitle());
			blogPreviewDTO.setDescription(blog.getDescription());
			blogPreviewDTO.setUsername(blog.getUser().getLogin());

			setBlogpreviewDTO.add(blogPreviewDTO);
		}

		return setBlogpreviewDTO;
	}

	public IUserRepository getUserRepository() {
		return userRepository;
	}

	public void removeBlog(BlogRemoveDTO blogRemoveDTO)
			throws NotLoggedInException,
			com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException,
			NotBlogOwnerException {

		try {
			User user = getUserRepository().findBySessionId(
					blogRemoveDTO.getSessionId());
			Blog blog = getBlogRepository().findById(blogRemoveDTO.getId());

			if (user.getId() == blog.getUser().getId()) {

				getBlogRepository().removeBlog(blog);

			} else {

				throw new NotBlogOwnerException();
			}
		} catch (UserSessionNotFoundException e) {
			throw new NotBlogOwnerException();
		} catch (BlogNotFoundException e) {
			throw new com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException();
		}

	}

	public void setBlogEntryRepository(IBlogEntryRepository blogEntryRepository) {
		this.blogEntryRepository = blogEntryRepository;
	}

	public void setBlogRepository(IBlogRepository blogRepository) {
		this.blogRepository = blogRepository;
	}

	public void setUserRepository(IUserRepository userRepository) {
		this.userRepository = userRepository;
	}

	public BlogEditDTO getBlogEditDTO(BlogEditIdDTO blogEditIdDTO)
			throws NotLoggedInException,
			NotBlogOwnerException, com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException {
		
		try {
			
			User user = getUserRepository().findBySessionId(blogEditIdDTO.getSessionId());
			
			Blog blog = getBlogRepository().getBlogEdit(blogEditIdDTO.getBlogId());
			
			if (user.getId() != blog.getUser().getId()) {
				throw new NotBlogOwnerException();
			}
			
			BlogEditDTO blogEditDTO = new BlogEditDTO();
			
			blogEditDTO.setDateLastUpdate(blog.getDateLastUpdate());
			blogEditDTO.setDescription(blog.getDescription());
			blogEditDTO.setId(blog.getId());
			blogEditDTO.setTitle(blog.getTitle());
			
			Map<BlogEntryDTO, List<BlogEntryCommentDTO>> mapBlogEntryDTOBlogEntryCommentDTO = new HashMap<BlogEntryDTO, List<BlogEntryCommentDTO>>();
			for (BlogEntry blogEntry : blog.getBlogEntry()) {
				
				BlogEntryDTO blogEntryDTO = new BlogEntryDTO();
				blogEntryDTO.setDate(blogEntry.getDate());
				blogEntryDTO.setId(blogEntry.getId());
				blogEntryDTO.setText(blogEntry.getText());
				blogEntryDTO.setTitle(blogEntry.getTitle());
				
				List<BlogEntryCommentDTO> listBlogEntryCommentDTO = new LinkedList<BlogEntryCommentDTO>();
				for (BlogEntryComment blogEntryComment : blogEntry.getBlogComment()) {
					
					BlogEntryCommentDTO blogEntryCommentDTO = new BlogEntryCommentDTO();
					blogEntryCommentDTO.setAuthorName(blogEntryComment.getAuthorName());
					blogEntryCommentDTO.setDate(blogEntryComment.getDate());
					blogEntryCommentDTO.setIdBlogEntry(blogEntry.getId());
					blogEntryCommentDTO.setIdBlogEntryComment(blogEntryComment.getId());
					blogEntryCommentDTO.setText(blogEntryComment.getText());
					
					listBlogEntryCommentDTO.add(blogEntryCommentDTO);
				}
				
				mapBlogEntryDTOBlogEntryCommentDTO.put(blogEntryDTO, listBlogEntryCommentDTO);
				
			}
			
			blogEditDTO.setMapBlogEntryDTOListBlogEntryCommentDTO(mapBlogEntryDTOBlogEntryCommentDTO);
			
			return blogEditDTO;
			
		} catch (UserSessionNotFoundException e) {
			
			throw new NotLoggedInException();
			
		} catch (BlogNotFoundException exception ) {
			
			throw new com.googlecode.hmvc4gwt.example.hmvcblog.service.dto.blog.exceptions.BlogNotFoundException();
			
		}
	}

}
